home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / Priss / source / convert.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-08-21  |  14.9 KB  |  697 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Audio processing library
  3. //    Copyright (C) 1998-2004 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <vd2/system/cpuaccel.h>
  20. #include <vd2/Priss/convert.h>
  21.  
  22. ///////////////////////////////////////////////////////////////////////////
  23. //
  24. //    scalar implementations
  25. //
  26. ///////////////////////////////////////////////////////////////////////////
  27.  
  28. void VDAPIENTRY VDConvertPCM32FToPCM8(void *dst0, const void *src0, uint32 samples) {
  29.     if (!samples)
  30.         return;
  31.  
  32.     uint8 *dst = (uint8 *)dst0;
  33.     const float *src = (const float *)src0;
  34.  
  35.     do {
  36.         const float ftmp = 98304.0f + *src++;
  37.         sint32 v = reinterpret_cast<const sint32&>(ftmp) - 0x47bfff80;
  38.  
  39.         if ((uint32)v >= 256)
  40.             v = (~v) >> 31;
  41.  
  42.         *dst++ = (uint8)v;
  43.     } while(--samples);
  44. }
  45.  
  46. void VDAPIENTRY VDConvertPCM32FToPCM16(void *dst0, const void *src0, uint32 samples) {
  47.     if (!samples)
  48.         return;
  49.  
  50.     sint16 *dst = (sint16 *)dst0;
  51.     const float *src = (const float *)src0;
  52.  
  53.     do {
  54.         const float ftmp = 384.0f + *src++;
  55.         sint32 v = reinterpret_cast<const sint32&>(ftmp) - 0x43bf8000;
  56.  
  57.         if ((uint32)v >= 0x10000)
  58.             v = (~v) >> 31;
  59.  
  60.         *dst++ = (sint16)(v - 0x8000);
  61.     } while(--samples);
  62. }
  63.  
  64. void VDAPIENTRY VDConvertPCM16ToPCM8(void *dst0, const void *src0, uint32 samples) {
  65.     if (!samples)
  66.         return;
  67.  
  68.     uint8 *dst = (uint8 *)dst0;
  69.     const sint16 *src = (const sint16 *)src0;
  70.  
  71.     do {
  72.         *dst++ = (uint8)((*src++ >> 8)^0x80);
  73.     } while(--samples);
  74. }
  75.  
  76. void VDAPIENTRY VDConvertPCM16ToPCM32F(void *dst0, const void *src0, uint32 samples) {
  77.     if (!samples)
  78.         return;
  79.  
  80.     float *dst = (float *)dst0;
  81.     const sint16 *src = (const sint16 *)src0;
  82.  
  83.     do {
  84.         *dst++ = (float)*src++ * (1.0f / 32768.0f);
  85.     } while(--samples);
  86. }
  87.  
  88. void VDAPIENTRY VDConvertPCM8ToPCM16(void *dst0, const void *src0, uint32 samples) {
  89.     if (!samples)
  90.         return;
  91.  
  92.     sint16 *dst = (sint16 *)dst0;
  93.     const uint8 *src = (const uint8 *)src0;
  94.  
  95.     do {
  96.         *dst++ = (sint16)(((int)*src++ - 0x80) << 8);
  97.     } while(--samples);
  98. }
  99.  
  100. void VDAPIENTRY VDConvertPCM8ToPCM32F(void *dst0, const void *src0, uint32 samples) {
  101.     if (!samples)
  102.         return;
  103.  
  104.     float *dst = (float *)dst0;
  105.     const uint8 *src = (const uint8 *)src0;
  106.  
  107.     do {
  108.         *dst++ = (float)((int)*src++ - 0x80) * (1.0f / 128.0f);
  109.     } while(--samples);
  110. }
  111.  
  112. sint16 VDAPIENTRY VDAudioFilterPCM16(const sint16 *src, const sint16 *filter, uint32 filterquadsize) {
  113.     sint32 v = 0x2000;
  114.  
  115.     const uint32 n = filterquadsize*4;
  116.     for(uint32 j=0; j<n; j+=4) {
  117.         v += (sint32)filter[j  ] * (sint32)src[j  ];
  118.         v += (sint32)filter[j+1] * (sint32)src[j+1];
  119.         v += (sint32)filter[j+2] * (sint32)src[j+2];
  120.         v += (sint32)filter[j+3] * (sint32)src[j+3];
  121.     }
  122.  
  123.     v = (v>>14) + 0x8000;
  124.  
  125.     if ((uint32)v >= 0x10000)
  126.         v = ~v >> 31;
  127.  
  128.     return (sint16)(v - 0x8000);
  129. }
  130.  
  131. void VDAPIENTRY VDAudioFilterPCM16End() {
  132. }
  133.  
  134. void VDAPIENTRY VDAudioFilterPCM16SymmetricArray(sint16 *dst, ptrdiff_t dst_stride, const sint16 *src, uint32 count, const sint16 *filter, uint32 filterquadsizeminus1) {
  135.     uint32 filterelsizeminus4 = filterquadsizeminus1*4;
  136.  
  137.     filter += filterquadsizeminus1*4;
  138.     src += filterquadsizeminus1*4;
  139.  
  140.     for(uint32 i=0; i<count; ++i) {
  141.         sint32 v = 0x2000 + (sint32)filter[0] * src[i];
  142.  
  143.         for(uint32 j=1; j<=filterelsizeminus4; j+=4) {
  144.             int k = -(int)j;
  145.             v += (sint32)filter[j  ] * ((sint32)src[i+j  ] + (sint32)src[i+k  ]);
  146.             v += (sint32)filter[j+1] * ((sint32)src[i+j+1] + (sint32)src[i+k-1]);
  147.             v += (sint32)filter[j+2] * ((sint32)src[i+j+2] + (sint32)src[i+k-2]);
  148.             v += (sint32)filter[j+3] * ((sint32)src[i+j+3] + (sint32)src[i+k-3]);
  149.         }
  150.  
  151.         v = (v>>14) + 0x8000;
  152.  
  153.         if ((uint32)v >= 0x10000)
  154.             v = ~v >> 31;
  155.  
  156.         *dst = (sint16)(v - 0x8000);
  157.         dst += dst_stride;
  158.     }
  159. }
  160.  
  161.  
  162. #ifdef _M_IX86
  163.  
  164. ///////////////////////////////////////////////////////////////////////////
  165. //
  166. //    MMX implementations
  167. //
  168. ///////////////////////////////////////////////////////////////////////////
  169.  
  170. #ifdef _MSC_VER
  171.     #pragma warning(disable: 4799)        // warning C4799: function has no MMX instruction
  172. #endif
  173.  
  174. namespace {
  175.     const __int64 x80b = 0x8080808080808080;
  176. }
  177.  
  178. void __declspec(naked) VDAPIENTRY VDConvertPCM16ToPCM8_MMX(void *dst0, const void *src0, uint32 samples) {
  179.  
  180.     __asm {
  181.         mov            eax, [esp+12]
  182.         mov            ecx, [esp+8]
  183.         mov            edx, [esp+4]
  184.         or            eax, eax
  185.         jz            xit
  186.  
  187.         movq        mm7, x80b
  188.         neg            eax
  189.         add            eax, 7
  190.         jc            nodq
  191.  
  192.         ;process quads (8n samples)
  193. dqloop:
  194.         movq        mm0, [ecx]
  195.         movq        mm1, [ecx+8]
  196.         psrlw        mm0, 8
  197.         add            edx, 8
  198.         psrlw        mm1, 8
  199.         add            ecx, 16
  200.         packuswb    mm0, mm1
  201.         pxor        mm0, mm7
  202.         add            eax, 8
  203.         movq        [edx-8], mm0
  204.         ja            dqloop
  205. nodq:
  206.         cmp            eax, 3
  207.         jg            noq
  208.         add            eax, 4
  209.  
  210.         ;process leftover quad (4 samples)
  211.         movq        mm0, [ecx]
  212.         add            edx, 4
  213.         psrlw        mm0, 8
  214.         packuswb    mm0, mm0
  215.         add            ecx, 8
  216.         pxor        mm0, mm7
  217.         movd        [edx-4], mm0
  218. noq:
  219.         sub            eax, 7
  220.         jz            xit2
  221.  
  222.         ;process leftover samples
  223.         movd        mm0, ebx
  224. singleloop:
  225.         mov            bl, byte ptr [ecx+1]
  226.         add            ecx, 2
  227.         xor            bl, 80h
  228.         mov            byte ptr [edx], bl
  229.         inc            edx
  230.         inc            eax
  231.         jne            singleloop
  232.         movd        ebx, mm0
  233. xit2:
  234.         emms
  235. xit:
  236.         ret
  237.     }
  238. }
  239.  
  240. void __declspec(naked) VDAPIENTRY VDConvertPCM8ToPCM16_MMX(void *dst0, const void *src0, uint32 samples) {
  241.     __asm {
  242.         mov        eax, [esp+12]
  243.         mov        ecx, [esp+8]
  244.         mov        edx, [esp+4]
  245.         or        eax, eax
  246.         jz        xit
  247.  
  248.         movq        mm7, x80b
  249.         neg            eax
  250.         movq        mm0, mm7
  251.         add            eax, 7
  252.         jc            nodq
  253.  
  254.         ;process quads (8n samples)
  255. dqloop:
  256.         pxor        mm0, [ecx]
  257.         pxor        mm1, mm1
  258.         add            edx, 16
  259.         punpcklbw    mm1, mm0
  260.         add            ecx, 8
  261.         pxor        mm2, mm2
  262.         punpckhbw    mm2, mm0
  263.         add            eax, 8
  264.         movq        [edx-16], mm1
  265.         movq        mm0, mm7
  266.         movq        [edx-8], mm2
  267.         ja            dqloop
  268. nodq:
  269.         cmp            eax, 3
  270.         jg            noq
  271.         add            eax, 4
  272.  
  273.         ;process leftover quad (4 samples)
  274.         movd        mm0, [ecx]
  275.         pxor        mm1, mm1
  276.         pxor        mm0, mm7
  277.         add            edx, 8
  278.         punpcklbw    mm1, mm0
  279.         add            ecx, 4
  280.         movq        [edx-8], mm1
  281. noq:
  282.         sub            eax, 7
  283.         jz            xit2
  284.  
  285.         ;process leftover samples
  286.         movd        mm0, ebx
  287. singleloop:
  288.         movzx        ebx, byte ptr [ecx]
  289.         add            edx, 2
  290.         shl            ebx, 8
  291.         inc            ecx
  292.         xor            ebx, 8000h
  293.         inc            eax
  294.         mov            word ptr [edx-2], bx
  295.         jne            singleloop
  296.         movd        ebx, mm0
  297. xit2:
  298.         emms
  299. xit:
  300.         ret
  301.     }
  302. }
  303.  
  304.  
  305. sint16 __declspec(naked) VDAPIENTRY VDAudioFilterPCM16_MMX(const sint16 *src, const sint16 *filter, uint32 filterquadsize) {
  306.     static const uint64 roundconst = 0x0000200000002000;
  307.  
  308.     __asm {
  309.         mov        eax,[esp+12]
  310.         mov        ecx,[esp+4]
  311.         shl        eax,3
  312.         mov        edx,[esp+8]
  313.         movq    mm0,roundconst
  314.         add        ecx, eax
  315.         add        edx, eax
  316.         neg        eax
  317. xloop:
  318.         movq    mm1,[ecx+eax]
  319.         pmaddwd    mm1,[edx+eax]
  320.         add        eax,8
  321.         paddd    mm0,mm1
  322.         jne        xloop
  323.  
  324.         punpckldq    mm1,mm0
  325.         paddd        mm0,mm1
  326.         psrad        mm0,14
  327.         packssdw    mm0,mm0
  328.         psrlq        mm0,48
  329.         movd    eax, mm0
  330.         ret
  331.     }
  332. }
  333.  
  334. void VDAPIENTRY VDAudioFilterPCM16End_MMX() {
  335.     __asm emms
  336. }
  337.  
  338. void __declspec(naked) VDAPIENTRY VDAudioFilterPCM16SymmetricArray_MMX(sint16 *dst, ptrdiff_t dst_stride, const sint16 *src_center, uint32 count, const sint16 *filter, uint32 filterquadsizeminus1) {
  339.     static const uint64 roundconst = 0x0000200000002000;
  340.  
  341.     __asm {
  342.         push        ebp
  343.         push        edi
  344.         push        esi
  345.         push        ebx
  346.         mov            ebx,[esp+24+16]
  347.         mov            ecx,[esp+12+16]
  348.         shl            ebx,4
  349.         mov            edx,[esp+20+16]
  350.         lea            ecx, [ecx+ebx+8]
  351.         lea            edx, [edx+ebx+8]
  352.         neg            ebx
  353.         mov            esi, [esp+16+16]
  354.         mov            edi, [esp+4+16]
  355.         mov            ebp, [esp+8+16]
  356.         add            ebp, ebp
  357. yloop:
  358.         mov            eax, ebx
  359.         movq        mm0,roundconst
  360.         movq        mm1,[ecx+eax-8]
  361.         pmaddwd        mm1,[edx+eax-8]
  362. xloop:
  363.         movq        mm2, [ecx+eax]
  364.         movq        mm3, [ecx+eax+8]
  365.         pmaddwd        mm2, [edx+eax]
  366.         pmaddwd        mm3, [edx+eax+8]
  367.         add            eax, 16
  368.         paddd        mm0, mm2
  369.         paddd        mm1, mm3
  370.         jne            xloop
  371.  
  372.         paddd        mm0, mm1
  373.         add            ecx, 2
  374.         punpckldq    mm1, mm0
  375.         paddd        mm0, mm1
  376.         psrad        mm0, 14
  377.         packssdw    mm0, mm0
  378.         psrlq        mm0, 48
  379.         movd        eax, mm0
  380.         mov            word ptr [edi], ax
  381.         add            edi, ebp
  382.         dec            esi
  383.         jne            yloop
  384.         emms
  385.         pop            ebx
  386.         pop            esi
  387.         pop            edi
  388.         pop            ebp
  389.         ret
  390.     }
  391. }
  392.  
  393. ///////////////////////////////////////////////////////////////////////////
  394. //
  395. //    SSE implementations
  396. //
  397. ///////////////////////////////////////////////////////////////////////////
  398.  
  399. static const float __declspec(align(16)) sse_32K[4]={32768.0f, 32768.0f, 32768.0f, 32768.0f};
  400. static const float __declspec(align(16)) sse_128[4]={128.0f, 128.0f, 128.0f, 128.0f};
  401. static const float __declspec(align(16)) sse_inv_32K[4]={1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f};
  402. static const float __declspec(align(16)) sse_inv_128[4]={1.0f/128.0f, 1.0f/128.0f, 1.0f/128.0f, 1.0f/128.0f};
  403.  
  404. void __declspec(naked) VDAPIENTRY VDConvertPCM32FToPCM16_SSE(void *dst, const void *src, uint32 samples) {
  405.     __asm {
  406.         push        ebx
  407.         mov            edx, [esp+4+4]
  408.         mov            ecx, [esp+8+4]
  409.         movaps        xmm1, sse_32K
  410.         mov            ebx, [esp+12+4]
  411.  
  412.         neg            ebx
  413.         jz            xit
  414.  
  415.         test        ecx, 15
  416.         jz            majorloopstart
  417. prealignloop:
  418.         movss        xmm0, [ecx]
  419.         add            ecx, 4
  420.         mulss        xmm0, xmm1
  421.         cvtps2pi    mm0, xmm0
  422.         packssdw    mm0, mm0
  423.         movd        eax, mm0
  424.         mov            word ptr [edx], ax
  425.         add            edx, 2
  426.         inc            ebx
  427.         jz            xit
  428.         test        ecx, 15
  429.         jnz            prealignloop
  430.  
  431. majorloopstart:
  432.         add            ebx, 3
  433.         jc            postloopstart
  434.  
  435. majorloop:
  436.         movaps        xmm0, [ecx]
  437.         add            ecx, 16
  438.         mulps        xmm0, xmm1
  439.         cvtps2pi    mm0, xmm0
  440.         movhlps        xmm0, xmm0
  441.         cvtps2pi    mm1, xmm0
  442.         packssdw    mm0, mm1
  443.         movq        [edx], mm0
  444.         add            edx, 8
  445.         add            ebx, 4
  446.         jnc            majorloop
  447.  
  448. postloopstart:
  449.         sub            ebx, 3
  450.         jz            xit
  451. postloop:
  452.         movss        xmm0, [ecx]
  453.         add            ecx, 4
  454.         mulss        xmm0, xmm1
  455.         cvtps2pi    mm0, xmm0
  456.         packssdw    mm0, mm0
  457.         movd        eax, mm0
  458.         mov            word ptr [edx], ax
  459.         add            edx, 2
  460.         inc            ebx
  461.         jnz            postloop
  462.  
  463. xit:
  464.         emms
  465.         pop            ebx
  466.         ret
  467.     }
  468. }
  469.  
  470. void __declspec(naked) VDAPIENTRY VDConvertPCM32FToPCM8_SSE(void *dst, const void *src, uint32 samples) {
  471.     __asm {
  472.         push        ebx
  473.         mov            edx, [esp+4+4]
  474.         mov            ecx, [esp+8+4]
  475.         movaps        xmm1, sse_128
  476.         mov            ebx, [esp+12+4]
  477.  
  478.         neg            ebx
  479.         jz            xit
  480.  
  481.         test        ecx, 15
  482.         jz            majorloopstart
  483. prealignloop:
  484.         movss        xmm0, [ecx]
  485.         add            ecx, 4
  486.         mulss        xmm0, xmm1
  487.         addss        xmm0, xmm1
  488.         cvtps2pi    mm0, xmm0
  489.         packssdw    mm0, mm0
  490.         packuswb    mm0, mm0
  491.         movd        eax, mm0
  492.         mov            byte ptr [edx], al
  493.         inc            edx
  494.         inc            ebx
  495.         jz            xit
  496.         test        ecx, 15
  497.         jnz            prealignloop
  498.  
  499. majorloopstart:
  500.         add            ebx, 3
  501.         jc            postloopstart
  502.  
  503. majorloop:
  504.         movaps        xmm0, [ecx]
  505.         add            ecx, 16
  506.         mulps        xmm0, xmm1
  507.         addps        xmm0, xmm1
  508.         cvtps2pi    mm0, xmm0
  509.         movhlps        xmm0, xmm0
  510.         cvtps2pi    mm1, xmm0
  511.         packssdw    mm0, mm1
  512.         packuswb    mm0, mm0
  513.         movd        [edx], mm0
  514.         add            edx, 4
  515.         add            ebx, 4
  516.         jnc            majorloop
  517.  
  518. postloopstart:
  519.         sub            ebx, 3
  520.         jz            xit
  521. postloop:
  522.         movss        xmm0, [ecx]
  523.         add            ecx, 4
  524.         mulss        xmm0, xmm1
  525.         addss        xmm0, xmm1
  526.         cvtps2pi    mm0, xmm0
  527.         packssdw    mm0, mm0
  528.         packuswb    mm0, mm0
  529.         movd        eax, mm0
  530.         mov            byte ptr [edx], al
  531.         inc            edx
  532.         inc            ebx
  533.         jnz            postloop
  534.  
  535. xit:
  536.         emms
  537.         pop            ebx
  538.         ret
  539.     }
  540. }
  541.  
  542. void __declspec(naked) VDAPIENTRY VDConvertPCM16ToPCM32F_SSE(void *dst, const void *src, uint32 samples) {
  543.     __asm {
  544.         movaps        xmm4, sse_inv_32K
  545.         push        ebx
  546.         mov            eax, [esp+12+4]
  547.         neg            eax
  548.         jz            xit
  549.         mov            ecx, [esp+8+4]
  550.         add            eax, eax
  551.         mov            edx, [esp+4+4]
  552.         sub            ecx, eax
  553.  
  554.         ;align destination
  555. alignloop:
  556.         test        edx, 15
  557.         jz            fastloop_start
  558.         movsx        ebx, word ptr [ecx+eax]
  559.         cvtsi2ss    xmm0, ebx
  560.         mulss        xmm0, xmm4
  561.         movss        [edx],xmm0
  562.         add            edx, 4
  563.         add            eax, 2
  564.         jne            alignloop
  565.         pop            ebx
  566.         ret
  567.  
  568. fastloop_start:
  569.         add            eax, 6
  570.         jns            skip_fastloop
  571.         jmp            short fastloop
  572.  
  573.         align        16
  574. fastloop:
  575.         movq        mm0, [ecx+eax-6]
  576.         pxor        mm1, mm1
  577.         punpckhwd    mm1, mm0
  578.         punpcklwd    mm0, mm0
  579.         psrad        mm0, 16
  580.         psrad        mm1, 16
  581.         cvtpi2ps    xmm0, mm0
  582.         cvtpi2ps    xmm1, mm1
  583.         movlhps        xmm0, xmm1
  584.         mulps        xmm0, xmm4
  585.         movaps        [edx], xmm0
  586.         add            edx, 16
  587.         add            eax, 8
  588.         jnc            fastloop
  589.         emms
  590. skip_fastloop:
  591.         sub            eax, 6
  592.         jz            xit
  593. tidyloop:
  594.         movsx        ebx, word ptr [ecx+eax]
  595.         cvtsi2ss    xmm0, ebx
  596.         mulss        xmm0, xmm4
  597.         movss        [edx],xmm0
  598.         add            edx, 4
  599.         add            eax, 2
  600.         jne            tidyloop
  601. xit:
  602.         pop            ebx
  603.         ret
  604.     }
  605. }
  606.  
  607. void __declspec(naked) VDAPIENTRY VDConvertPCM8ToPCM32F_SSE(void *dst, const void *src, uint32 samples) {
  608.     __asm {
  609.         movaps        xmm1, sse_inv_128
  610.         push        ebx
  611.         mov            eax, [esp+12+4]
  612.         neg            eax
  613.         jz            xit
  614.         mov            ecx, [esp+8+4]
  615.         mov            edx, [esp+4+4]
  616.         sub            ecx, eax
  617. lup:
  618.         movzx        ebx, byte ptr [ecx+eax]
  619.         sub            ebx, 80h
  620.         cvtsi2ss    xmm0, ebx
  621.         mulss        xmm0, xmm1
  622.         movss        [edx],xmm0
  623.         add            edx, 4
  624.         inc            eax
  625.         jne            lup
  626. xit:
  627.         pop            ebx
  628.         ret
  629.     }
  630. }
  631. #endif
  632.  
  633. ///////////////////////////////////////////////////////////////////////////
  634. //
  635. //    vtables
  636. //
  637. ///////////////////////////////////////////////////////////////////////////
  638.  
  639. static const tpVDConvertPCM g_VDConvertPCMTable_scalar[3][3]={
  640.     {    0,                            VDConvertPCM8ToPCM16,            VDConvertPCM8ToPCM32F        },
  641.     {    VDConvertPCM16ToPCM8,        0,                                VDConvertPCM16ToPCM32F        },
  642.     {    VDConvertPCM32FToPCM8,        VDConvertPCM32FToPCM16,            0                            },
  643. };
  644.  
  645. #ifdef _M_IX86
  646. static const tpVDConvertPCM g_VDConvertPCMTable_MMX[3][3]={
  647.     {    0,                            VDConvertPCM8ToPCM16_MMX,        VDConvertPCM8ToPCM32F        },
  648.     {    VDConvertPCM16ToPCM8_MMX,    0,                                VDConvertPCM16ToPCM32F        },
  649.     {    VDConvertPCM32FToPCM8,        VDConvertPCM32FToPCM16,            0                            },
  650. };
  651.  
  652. static const tpVDConvertPCM g_VDConvertPCMTable_SSE[3][3]={
  653.     {    0,                            VDConvertPCM8ToPCM16_MMX,        VDConvertPCM8ToPCM32F_SSE    },
  654.     {    VDConvertPCM16ToPCM8_MMX,    0,                                VDConvertPCM16ToPCM32F_SSE    },
  655.     {    VDConvertPCM32FToPCM8_SSE,    VDConvertPCM32FToPCM16_SSE,        0                            },
  656. };
  657. #endif
  658.  
  659. tpVDConvertPCMVtbl VDGetPCMConversionVtable() {
  660. #ifdef _M_IX86
  661.     uint32 exts = CPUGetEnabledExtensions();
  662.  
  663.     if (exts & CPUF_SUPPORTS_MMX) {
  664.         if (exts & CPUF_SUPPORTS_SSE)
  665.             return g_VDConvertPCMTable_SSE;
  666.         else
  667.             return g_VDConvertPCMTable_MMX;
  668.     }
  669. #endif
  670.     return g_VDConvertPCMTable_scalar;
  671. }
  672.  
  673. static const VDAudioFilterVtable g_VDAudioFilterVtable_scalar = {
  674.     VDAudioFilterPCM16,
  675.     VDAudioFilterPCM16End,
  676.     VDAudioFilterPCM16SymmetricArray
  677. };
  678.  
  679. #ifdef _M_IX86
  680. static const VDAudioFilterVtable g_VDAudioFilterVtable_MMX = {
  681.     VDAudioFilterPCM16_MMX,
  682.     VDAudioFilterPCM16End_MMX,
  683.     VDAudioFilterPCM16SymmetricArray_MMX
  684. };
  685. #endif
  686.  
  687. const VDAudioFilterVtable *VDGetAudioFilterVtable() {
  688. #ifdef _M_IX86
  689.     uint32 exts = CPUGetEnabledExtensions();
  690.  
  691.     if (exts & CPUF_SUPPORTS_MMX)
  692.         return &g_VDAudioFilterVtable_MMX;
  693. #endif
  694.  
  695.     return &g_VDAudioFilterVtable_scalar;
  696. }
  697.